﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.Ex.Communication.Net.Ftp
{
    /// <summary>
    /// ftp命令基类
    /// </summary>
    internal abstract class FtpCommandAbs : IFtpCommand
    {
        /// <summary>
        /// true：当前命令异步执行;false:当前命令同步执行
        /// </summary>
        private bool _asynExcute = false;




        public FtpCommandAbs(bool asynExcute = false)
        {
            this._asynExcute = asynExcute;
        }



        /// <summary>
        /// 命令名称集合
        /// </summary>
        public string[] Names
        {
            get { return GetNames(); }
        }

        protected abstract string[] GetNames();


        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="session">ftp会话</param>
        /// <param name="command">命令</param>
        /// <param name="commandParam">命令参数</param>
        public void Excute(FtpSession session, string command, string commandParam)
        {
            if (!this.CheckLastCommand(session))
            {
                IFtpResponse res = new FtpCodeResponse(FtpStatusCodes.Code503);
                session.Send(res);
                return;
            }

            if (this._asynExcute)
            {
                Task.Factory.StartNew(this.ThreadExcuteMethod, new AsynExcuteCommandThreadParam(session, command, commandParam));
            }
            else
            {

                this.InnerExcute(session, command, commandParam);
            }
        }

        private void ThreadExcuteMethod(object obj)
        {
            var param = (AsynExcuteCommandThreadParam)obj;
            this.InnerExcute(param.Session, param.Command, param.CommandParam);
        }


        private void InnerExcute(FtpSession session, string command, string commandLine)
        {
            try
            {
                IFtpResponse res = this.PrimitiveExcute(session, command, commandLine);
                session.Send(res);
            }
            catch (Exception ex)
            {
                ZLoger.Error(ex);

                try
                {
                    session.Send(new FtpCodeResponse(FtpStatusCodes.Code451));
                }
                catch (IOException ioex)
                {
                    ZLoger.Warn(ioex);
                    session.OnRaiseSessionCloseCallback();
                }
                catch (Exception ex2)
                {
                    ZLoger.Error(ex2);
                    session.OnRaiseSessionCloseCallback();
                }
            }
        }


        /// <summary>
        /// 执行ftp命令
        /// </summary>
        /// <param name="session">ftp会话</param>
        /// <param name="command">命令</param>
        /// <param name="commandParam">命令参数</param>
        /// <returns>执行响应</returns>
        protected virtual IFtpResponse PrimitiveExcute(FtpSession session, string command, string commandParam)
        {
            return FtpCodeResponse.NotImplementedCommandResponse;
        }

        /// <summary>
        /// 检查之前的命令是否满足在当前命令要求,即必须执行前一个命令，才能执行当前命令
        /// 满足要求返回true,不满足返回false
        /// </summary>
        /// <param name="session">ftp会话</param>
        /// <returns>满足要求返回true,不满足返回false</returns>
        protected virtual bool CheckLastCommand(FtpSession session)
        {
            return true;
        }
    }
}
